package ch.ethz.fcl.metrobuzz.data.loader.MRTUncertain;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.loader.PublicTransitType;
import ch.ethz.fcl.metrobuzz.data.scene.spacetime.Agent;
import ch.ethz.fcl.metrobuzz.data.scene.spacetime.Itinerary;
import ch.ethz.fcl.metrobuzz.data.transit.Stop;
import ch.ethz.fcl.metrobuzz.data.transit.TransitLine;
import ch.ethz.fcl.metrobuzz.data.transit.TransitRoute;
import ch.ethz.fcl.metrobuzz.tools.MBTools;

/**
 * Load processed EZLink data
 * 
 * @author Zeng Wei
 * @email zeng@arch.ethz.ch
 * 
 */
public class MRTUncertaintyLoader {
	private int tripsLimit = 1000000;

	@SuppressWarnings("resource")
	public void load(MBData data, String filePath) {
		int numOfTrips = 0;
		filePath = "res/Singapore/sampled_raw_data_MRTUncertain";

		try {
			BufferedReader reader = new BufferedReader(new FileReader(filePath));
			reader.readLine();// first line is skipped
			String tripEntry = null;

			while ((tripEntry = reader.readLine()) != null
					&& numOfTrips < tripsLimit) {
				inputProcess(data, tripEntry);
				numOfTrips++;
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("Total " + numOfTrips + " trip entries loaded");
	}

	private void inputProcess(MBData data, String input) throws Exception {
		String[] fields = input.split(",");

		if (fields.length != 15) {
			throw new Exception("Wrong input fields");
		}

		long tripId = Long.parseLong(fields[0]); // trip id
		long cardId = Long.parseLong(fields[1]); // agent/card id

		Stop boardStop, alightStop;
		PublicTransitType type;
		if (fields[3].equals("RTS"))
			type = PublicTransitType.RTS;
		else if (fields[3].equals("Bus"))
			type = PublicTransitType.BUS;
		else {
			throw new Exception("Unknown trip type");
		}

		String boardStopName = fields[7].replace("STN ", "");
		String alightStopName = fields[8].replace("STN ", "");

		// some people take wrong bus
		// 102465695383,9000238562880800,Adult,Bus,199
		// ,1,8121,22009,22009,11/04/2011,20:32:13.000000,0.100,4.100,0.02,2
		if (boardStopName.endsWith(alightStopName))
			return;

		float startTime = MBTools.convertTimeFromString(fields[10]);
		float travelTime = -1;

		// if people don't tap out, ignore this field
		if (!fields[12].equals("?")) {
			travelTime = Float.parseFloat(fields[12]) * 60;
		} else
			return;

		int transferNum = Integer.parseInt(fields[14]);

		Agent agent = data.getScene().getAgentMap().get(cardId);
		Itinerary itinerary = null;
		if (agent == null) {
			agent = new Agent(cardId);
			data.getScene().addAgent(cardId, agent);
			itinerary = new Itinerary(agent);
		} else
			itinerary = agent.getItinerary();

		if (type == PublicTransitType.BUS) {
			// field 4 is transit line number, 5 is direction (0/1), 6 is
			// registration number
			TransitLine transit = data.getPublicTransit().getLine(
					fields[4].trim());

			if (transit == null)
				return;

			int direction = Integer.parseInt(fields[5]);
			// int busRegNum = Integer.parseInt(fields[6]);

			if (boardStopName.length() < 5)
				boardStopName = "0" + boardStopName;
			if (alightStopName.length() < 5)
				alightStopName = "0" + alightStopName;
			boardStop = data.getPublicTransit().getStopByStopId(boardStopName);
			alightStop = data.getPublicTransit()
					.getStopByStopId(alightStopName);

			if (boardStop == null)
				return;

			if (alightStop == null)
				return;

			if (transit != null && travelTime != -1) {

				TransitRoute route = transit.getRoute(direction, boardStop,
						alightStop);

				if (route != null) {
					List<Integer> nodeIndices = itinerary.getNodeIndices(data,
							startTime, startTime + travelTime, route,
							boardStop, alightStop);

					itinerary.addTrip(data, nodeIndices, tripId, transferNum,
							startTime, startTime + travelTime, 1);
				}
			}
		} else if (type == PublicTransitType.RTS) { // if it is MRT lines
			String stationIDs = boardStopName;
			String[] stations = stationIDs.split("->");

			float probability = Float.parseFloat(alightStopName);

			if (stations != null && travelTime != -1) {
				List<Integer> nodeIndices = new ArrayList<Integer>();

				for (String stationID : stations)
					nodeIndices.add(data.getScene().getNodeIndex(stationID));

				itinerary.addTrip(data, nodeIndices, tripId, transferNum,
						startTime, startTime + travelTime, probability);
			}
		}
	}
}
